package com.yxd.bdmapdemo;

import android.content.Context;
import android.os.Vibrator;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.BDNotifyListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;

import java.util.ArrayList;
import java.util.List;

import static android.content.Context.VIBRATOR_SERVICE;

/**
 * Created by dong on 2017/5/13.
 */

public class BdLocManager {

    private Context context;
    private BaiduMap mBaiduMap;
    private Overlay myMarker;
    private boolean isFirst = true;

    public BdLocManager(Context context, BaiduMap baiduMap) {
        this.context = context;
        this.mBaiduMap=baiduMap;
    }

    //LocationClient类是定位SDK的核心类
    public LocationClient mLocationClient = null;
    public BDLocationListener myListener = new MyLocationListener();


    public void registerLocLisener() {
        //声明LocationClient类
        mLocationClient = new LocationClient(context);
        //注册监听函数
        mLocationClient.registerLocationListener(myListener);
        initLocation();
    }

    /**
     * LocationClientOption类，该类用来设置定位SDK的定位方式
     * 高精度定位模式：这种定位模式下，会同时使用网络定位和GPS定位，优先返回最高精度的定位结果；
     * 低功耗定位模式：这种定位模式下，不会使用GPS进行定位，只会使用网络定位（WiFi定位和基站定位）；
     * 仅用设备定位模式：这种定位模式下，不需要连接网络，只使用GPS进行定位，这种模式下不支持室内环境的定位。
     */
    public void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        //可选，默认高精度，设置定位模式，高精度，低功耗，仅设备传感器
        option.setCoorType("bd09ll");//gcj02：国测局坐标；bd09：百度墨卡托坐标；bd09ll：百度经纬度坐标；
        //可选，默认gcj02，设置返回的定位结果坐标系
        int span = 15000;
        option.setScanSpan(span);
        //可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);
        //可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true);
        //可选，默认false,设置是否使用gps
        option.setLocationNotify(true);
        //可选，默认false，设置是否当GPS有效时按照1S/1次频率输出GPS结果
        option.setIsNeedLocationDescribe(true);
        //可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);
        //可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false);
        //可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false);
        //可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false);
        //可选，默认false，设置是否需要过滤GPS仿真结果，默认需要
        mLocationClient.setLocOption(option);
    }

    /**
     * 如果开发者想按照自己逻辑请求定位，可以在start之后按照自己的逻辑请求locationclient.requestLocation()函数，会主动触发定位SDK内部定位逻辑，等待定位回调即可。
     */
    public void start(){
       // 开始定位
        if (mLocationClient != null) {
            mLocationClient.start();
        }
    }
    public void stop(){
        if (mLocationClient != null) {
            mLocationClient.stop();//停止定位
        }
    }

    /**
     *
     * location.getLocType();//获取定位返回错误码:
     * 61 ： GPS定位结果，GPS定位成功。
     * 62 ： 无法获取有效定位依据，定位失败，请检查运营商网络或者WiFi网络是否正常开启，尝试重新请求定位。
     * 63 ： 网络异常，没有成功向服务器发起请求，请确认当前测试手机网络是否通畅，尝试重新请求定位。
     * 65 ： 定位缓存的结果。
     * 66 ： 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果。
     * 67 ： 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果。
     * 68 ： 网络连接失败时，查找本地离线定位时对应的返回结果。
     * 161： 网络定位结果，网络定位成功。
     * 162： 请求串密文解析失败，一般是由于客户端SO文件加载失败造成，请严格参照开发指南或demo开发，放入对应SO文件。
     * 167： 服务端定位失败，请您检查是否禁用获取位置信息权限，尝试重新请求定位。
     * 502： AK参数错误，请按照说明文档重新申请AK。
     * 505：AK不存在或者非法，请按照说明文档重新申请AK。
     * 601： AK服务被开发者自己禁用，请按照说明文档重新申请AK。
     * 602： key mcode不匹配，您的AK配置过程中安全码设置有问题，请确保：SHA1正确，“;”分号是英文状态；且包名是您当前运行应用的包名，请按照说明文档重新申请AK。
     * 501～700：AK验证失败，请按照说明文档重新申请AK。
     */

    private BDLocation mLocation;
    public class MyLocationListener implements BDLocationListener {

        /**
         * @param location BDLocation类，封装了定位SDK的定位结果
         */
        @Override
        public void onReceiveLocation(BDLocation location) {
            mLocation=location;
            /*String country= location.getAddress().country;
            String countryCode= location.getAddress().countryCode;
            String province= location.getAddress().province;
            String city= location.getAddress().city;
            String cityCode= location.getAddress().cityCode;
            String street= location.getAddress().street;
            String streetNumber= location.getAddress().streetNumber;

            String address= location.getAddress().address;
            String district= location.getAddress().district;//区、县
            L.d(country+"-"+countryCode+"-"+province+"-"+city+"-"+cityCode+"-"+district+"-"+street+"-"+streetNumber+"-"+address);*/

            if (isFirst) {
                //让地图中心点跑到我的定位的位置
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, 18);//12为缩放级别
                //此方法无动画效果
                //  bdMap.setMapStatus(mapStatusUpdate);
                mBaiduMap.animateMapStatus(mapStatusUpdate, 1000);//动画效果
                showCurMarker(latLng);
               // addText(location.getLatitude(), location.getLongitude());

                isFirst = false;
            }

          //  stop();

            //获取定位结果
            StringBuffer sb = new StringBuffer(256);
            sb.append("time : ");
            sb.append(location.getTime());    //获取定位时间
            sb.append("\nerror code : ");
            sb.append(location.getLocType());    //获取类型类型
            sb.append("\nlatitude : ");
            sb.append(location.getLatitude());    //获取纬度信息
            sb.append("\nlontitude : ");
            sb.append(location.getLongitude());    //获取经度信息
            sb.append("\nradius : ");
            sb.append(location.getRadius());    //获取定位精准度
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                // GPS定位结果
                sb.append("\nspeed : ");
                sb.append(location.getSpeed());    // 单位：公里每小时
                sb.append("\nsatellite : ");
                sb.append(location.getSatelliteNumber());    //获取卫星数
                sb.append("\nheight : ");
                sb.append(location.getAltitude());    //获取海拔高度信息，单位米,这个误差很大
                sb.append("\ndirection : ");
                sb.append(location.getDirection());    //获取方向信息，单位度
                sb.append("\naddr : ");
                sb.append(location.getAddrStr());    //获取地址信息
                sb.append("\ndescribe : ");
                sb.append("gps定位成功");
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                // 网络定位结果
                sb.append("\naddr : ");
                sb.append(location.getAddrStr());    //获取地址信息
                sb.append("\noperationers : ");
                sb.append(location.getOperators());    //获取运营商信息
                sb.append("\ndescribe : ");
                sb.append("网络定位成功");
            } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
                // 离线定位结果
                sb.append("\ndescribe : ");
                sb.append("离线定位成功，离线定位结果也是有效的");
            } else if (location.getLocType() == BDLocation.TypeServerError) {
                sb.append("\ndescribe : ");
                sb.append("服务端网络定位失败，可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com，会有人追查原因");
            } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                sb.append("\ndescribe : ");
                sb.append("网络不同导致定位失败，请检查网络是否通畅");
            } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                sb.append("\ndescribe : ");
                sb.append("无法获取有效定位依据导致定位失败，一般是由于手机的原因，处于飞行模式下一般会造成这种结果，可以试着重启手机");
            }

            sb.append("\nlocationdescribe : ");
            sb.append(location.getLocationDescribe());    //位置语义化信息
            List<Poi> list = location.getPoiList();    // POI数据
            if (list != null) {
                sb.append("\npoilist size = : ");
                sb.append(list.size());
                for (Poi p : list) {
                    sb.append("\npoi= : ");
                    sb.append(p.getId() + " " + p.getName() + " " + p.getRank());
                }
            }

            Log.i("BaiduLocationApiDem", sb.toString());

        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {

        }
    }

    private void showCurMarker(LatLng latLng){

        if (myMarker != null && myMarker.isVisible()) {
            myMarker.remove();
        }
        addMarker(latLng.latitude,latLng.longitude);
        /*if (textOverlay != null && textOverlay.isVisible()) {
            textOverlay.remove();
        }*/
    }

    private void addMarker(double latitude, double lontitude) {
        //定义Maker坐标点
        LatLng point = new LatLng(latitude, lontitude);//纬度经度
        //构建Marker图标

        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_focuse_mark);
        BitmapDescriptor bitmap2 = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_mark);
        ArrayList<BitmapDescriptor> list = new ArrayList<>();
        list.add(bitmap);
        list.add(bitmap2);
        //构建MarkerOption，用于在地图上添加Marker
        OverlayOptions option = new MarkerOptions()
                .position(point)
                .animateType(MarkerOptions.MarkerAnimateType.grow) // 生长动画
                .icons(list);//添加多个图标
        //.icon(bitmap);//添加一个图标
        //在地图上添加Marker，并显示

        myMarker = mBaiduMap.addOverlay(option);
    }

    /**--------------------  位置提醒相关代码  ----------------------------*/
    NotifyLister mNotifyer;
    Vibrator vibrator;

    private void initLocNotify() {
        mNotifyer = new NotifyLister();
        mNotifyer.SetNotifyLocation(42.03249652949337, 113.3129895882556, 3000, "gps");
        //4个参数代表要位置提醒的点的坐标，具体含义依次为：纬度，经度，距离范围，坐标系类型(gcj02,gps,bd09,bd09ll)
        mLocationClient.registerNotify(mNotifyer);
    }
    //注册位置提醒监听事件后，可以通过SetNotifyLocation 来修改位置提醒设置，修改后立刻生效。

    //BDNotifyListner实现
    class NotifyLister extends BDNotifyListener {

        public void onNotify(BDLocation mlocation, float distance){

            vibrator = (Vibrator) context.getSystemService(VIBRATOR_SERVICE);
            vibrator.vibrate(1000);
            //振动提醒已到设定位置附近
            // 设置震动周期
           // vibrator.vibrate(new long[] { 100, 100, 100, 1000 }, 0);
        }
    }

    public void cancelNotify(){
        //取消位置提醒
        mLocationClient.removeNotifyEvent(mNotifyer);
    }

    private void cancel(){
        // 取消震动
        vibrator.cancel();
    }


}
